package cn.net.dpi.shp.task;

import cn.hutool.http.HttpUtil;
import cn.net.dpi.shp.constants.Constants;
import cn.net.dpi.shp.service.ParseService;
import cn.net.dpi.shp.util.JSONUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

@Component
public class TaskExecutionService {
    private final Logger logger = LoggerFactory.getLogger(String.format(Constants.TASK_LOG_LOGGER_NAME_FORMAT, getClass()));
    private static final int EXEC_STATE_FAILURE = 6;
    private static final int EXEC_STATE_SUCCESS = 7;
    /**
     * http请求超时时间，单位毫秒
     */
    private static int HTTP_POST_TIMEOUT_MS = 60000;
    private static String outBaseDataDir;
    private static String preTaskTypeName = "RINEX-CONVERT";
    private static String preTaskOutPutName = "output1";

    private TaskExecutionConfig taskExecutionConfig;
    private TaskExecuteParameters parameters = null;
    private Map<String, List<Map<String, String>>> outputMap = new HashMap<>();

    @Resource
    private ParseService parseService;

    public void init(TaskExecutionConfig taskExecutionConfig) {
        this.taskExecutionConfig = taskExecutionConfig;
        String taskParams = this.taskExecutionConfig.getTaskParams();
        logger.info("task params: {}", taskParams);
        try {
            if (StringUtils.isEmpty(taskParams)) {
                return;
            }
            parameters = JSONUtils.parseObject(taskParams, TaskExecuteParameters.class);
            byte[] o = Base64.getDecoder().decode(parameters.getOutput());
            outputMap = JSONUtils.parseObject(new String(o), new TypeReference<Map<String, List<Map<String, String>>>>() {
            });
        } catch (Exception e) {
            logger.error("task params parse error", e);
        }
    }

    public boolean execute() {
        logger.info("Start execute");
        if (null == parameters) {
            logger.info("task params is null");
            return false;
        }
        String inBaseDataDir = null;
        List<Map<String, String>> temps = outputMap.get(preTaskTypeName);
        for (Map<String, String> temp : temps) {
            if (temp.get("name").equals(preTaskOutPutName)) {
                inBaseDataDir = temp.get("file");
            }
        }
        // 参数填充
        outBaseDataDir = parameters.getBaseDataDir() + "/shp-parse";

        /**
         * 写具体的实现
         */
        parseService.parserShpFile(parameters.getBaseDataDir());


//        doSend(true, "shp-parse start at:" + LocalDateTime.now());
        return true;
    }

    /**
     * 回调调用系统API返回执行结果
     *
     * @param execResult
     */
    public void doSend(boolean execResult, String msg) {
        int maxRetryCount = 3;
        int retryCount = 0;
        boolean success = false;
        do {
            try {
                send(execResult, msg);
                success = true;
            } catch (Exception ex) {
                logger.error(String.format("send exec result  error. retryCount= %d", retryCount), ex);
                retryCount++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        } while (retryCount < maxRetryCount && !success);
        if (!success) {
            logger.error("发送执行结果失败.");
        }
    }

    private void send(boolean execResult, String msg) {
        HashMap<String, Object> paramMap = new HashMap<>();
        if (null != parameters) {
            paramMap.put("processInstanceId", parameters.getProcessInstanceId());
            paramMap.put("taskInstanceId", parameters.getTaskInstanceId());
        }
        paramMap.put("state", execResult ? EXEC_STATE_SUCCESS : EXEC_STATE_FAILURE);
        paramMap.put("endTime", execResult ? null : LocalDateTime.now());
//        try {
//            List<String> lines = FileUtils.readLines(new File(this.taskExecutionConfig.getLogPath()), StandardCharsets.UTF_8);
//            String log = StringUtils.join(lines, "<br/>");
//            paramMap.put("log", log);
//        } catch (Exception e) {
//            logger.warn("读取日志文件异常", e);
//        }
        List<Map<String, String>> outputList = new ArrayList<>();
        Map<String, String> outputMap = new HashMap<>();
        outputMap.put("name", "shp-parse-out");
        outputMap.put("table", "");
        outputMap.put("file", outBaseDataDir);
        outputMap.put("msg", msg);
        outputList.add(outputMap);
        paramMap.put("output", outputList);
        String body = JSONUtils.toJsonString(paramMap);
        logger.info("回调调用系统API返回执行结果.request url:{}, body:{}",
                parameters.getCallback(), body);
        HttpUtil.post(parameters.getCallback(), body, HTTP_POST_TIMEOUT_MS);
    }
}
